package com.bdmc.smokesensor.controller;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bdmc.smokesensor.Utils.Constants;
import com.bdmc.smokesensor.Utils.DateUtil;
import com.bdmc.smokesensor.Utils.Msg;
import com.bdmc.smokesensor.Utils.ResultUtil;
import com.bdmc.smokesensor.Utils.http.HttpAPIService;
import com.bdmc.smokesensor.Utils.http.HttpResult;
import com.bdmc.smokesensor.entity.Smk_Alarm;
import com.bdmc.smokesensor.entity.Smk_Buildings;
import com.bdmc.smokesensor.entity.Smk_Devices;
import com.bdmc.smokesensor.entity.Smk_GroupCompany;
import com.bdmc.smokesensor.entity.Smk_HeartBeat;
import com.bdmc.smokesensor.entity.Sys_Department;
import com.bdmc.smokesensor.entity.Sys_Log;
import com.bdmc.smokesensor.entity.Sys_User;
import com.bdmc.smokesensor.iservices.ISmk_AlarmService;
import com.bdmc.smokesensor.iservices.ISmk_BuildingsService;
import com.bdmc.smokesensor.iservices.ISmk_DevicesService;
import com.bdmc.smokesensor.iservices.ISmk_GroupCompanyService;
import com.bdmc.smokesensor.iservices.ISmk_HeartBeatService;
import com.bdmc.smokesensor.iservices.ISys_DepService;
import com.bdmc.smokesensor.iservices.ISys_UserService;
import com.bdmc.smokesensor.models.alarm.AlarmData;
import com.bdmc.smokesensor.models.device.DeviceMessage;
import com.bdmc.smokesensor.models.device.DeviceModal;
import com.bdmc.smokesensor.services.Sys_LogService;
import com.bdmc.smokesensor.websocket.MyWebSocket;
import com.github.qcloudsms.SmsSingleSender;
import com.github.qcloudsms.SmsSingleSenderResult;
import com.github.qcloudsms.TtsVoiceSender;
import com.github.qcloudsms.TtsVoiceSenderResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import io.netty.util.internal.StringUtil;

@RestController
@RequestMapping(value = "/msg")
public class MessageController extends BaseController {

    @Autowired
    private ISmk_DevicesService _devSvs;

    @Autowired
    private ISmk_AlarmService _alarmSvs;

    @Autowired
    private ISys_DepService _depSvs;

    @Autowired
    private ISmk_GroupCompanyService _gcSvs;

    @Autowired
    private ISys_UserService _userSvs;

    @Autowired
    private ISmk_BuildingsService _buildSvs;

    @Autowired
    private HttpAPIService _apiSvs;

    @Autowired
    private ISmk_HeartBeatService _heartSvs;

    @Autowired
    public Sys_LogService _logSvs;

    @PostMapping(value = "/ct")
    public Msg ctmsg(@RequestBody(required = false) String json) {
        if (!StringUtil.isNullOrEmpty(json)) {
            logger.debug(json);
        }

        return ResultUtil.success();
    }

    /** * 接收三江推送信息 * */
    // 修改[{"devices":[{"deviceName":"烟感865353030407958","installAddress":"北京天安门","modifyTime":"2018-11-02T02:45:56.425Z","deviceId":"3jyun-865353030407958"}],"replyTo":"/Agent/7365d3a54654_25/Rcv","action":"device-change","type":"update","seq":"7365d3a54654_25_1541126756629_40"}]
    // 删除[{"devices":[{"deviceId":"3jyun-865353030407958"}],"replyTo":"/Agent/119e9d026aa3_25/Rcv","action":"device-change","type":"delete","seq":"119e9d026aa3_25_1541127954275_43"}]
    // 添加[{"devices":[{"deviceId":"3jyun-865353030407958","deviceType":"CTNBSmokeSensor","deviceName":"烟感865353030407958","location":[116.397558,39.906925],"installAddress":"北京天安门","extension":{"monitorId":169,"IMEI":"865353030407958","Platform":"3jyun"},"deviceTypeName":"NB-IoT烟感","modifyTime":"2018-11-02T03:11:49.212Z"}],"replyTo":"/Agent/119e9d026aa3_35/Rcv","action":"device-change","type":"add","seq":"119e9d026aa3_35_1541128309416_41"}]
    // 设备离线 :
    // ["{\"deviceType\":\"CTNBSmokeSensor\",\"ext\":{\"IMEI\":\"865352032725243\",\"location\":{\"lon\":116.39756,\"lat\":39.906925}},\"streamId\":\"online\",\"data\":\"设备离线\",\"level\":1,\"isPopup\":true,\"oid\":1542866445993,\"rawData\":\"0099\",\"type\":\"alarm\",\"deviceId\":\"9997d18b-41c3-4854-a3dc-3ae250881b78\",\"deviceName\":\"测试烟感5243\",\"at\":\"2018-11-22
    // 14:00:45\",\"location\":\"湖北省武汉市光谷科技港\"}"]
    // 离线
    // ["{\"deviceType\":\"CTNBSmokeSensor\",\"ext\":{\"IMEI\":\"865352032725243\",\"location\":{\"lon\":116.39756,\"lat\":39.906925}},\"streamId\":\"online\",\"data\":\"设备离线\",\"level\":1,\"isPopup\":true,\"oid\":1542866445993,\"rawData\":\"0099\",\"type\":\"alarm\",\"deviceId\":\"9997d18b-41c3-4854-a3dc-3ae250881b78\",\"deviceName\":\"测试烟感5243\",\"at\":\"2018-11-22
    // 14:00:45\",\"location\":\"湖北省武汉市光谷科技港\"}"]
    // 低压告警["{\"deviceType\":\"CTNBSmokeSensor\",\"ext\":{\"IMEI\":\"865352032725243\",\"location\":{\"lon\":116.39756,\"lat\":39.906925}},\"streamId\":\"power\",\"data\":\"[告警]光电探测器低电压告警\",\"level\":1,\"isPopup\":true,\"oid\":1542693645740,\"rawData\":\"020300\",\"type\":\"alarm\",\"deviceId\":\"9997d18b-41c3-4854-a3dc-3ae250881b78\",\"deviceName\":\"测试烟感5243\",\"at\":\"2018-11-20
    // 14:00:45\",\"location\":\"湖北省武汉市光谷科技港\"}"]
    // 火警["{\"deviceType\":\"CTNBSmokeSensor\",\"ext\":{\"IMEI\":\"865352032725243\",\"location\":{\"lon\":116.39756,\"lat\":39.906925}},\"streamId\":\"fireAlarm\",\"data\":\"[火警]光电探测器[火警]\",\"level\":2,\"isPopup\":true,\"oid\":1541662857559,\"rawData\":\"020100\",\"type\":\"alarm\",\"deviceId\":\"9997d18b-41c3-4854-a3dc-3ae250881b78\",\"deviceName\":\"测试烟感5243\",\"at\":\"2018-11-08
    // 15:40:57\",\"location\":\"湖北省武汉市光谷科技港\"}"]
    // 清除火警 :
    // ["{\"deviceType\":\"CTNBSmokeSensor\",\"ext\":{\"IMEI\":\"865353030407958\",\"location\":{\"lon\":116.39756,\"lat\":39.906925}},\"streamId\":\"fireAlarm\",\"data\":\"[火警清除]光电探测器火警清除\",\"level\":2,\"isPopup\":true,\"oid\":1541733511002,\"rawData\":\"020400\",\"type\":\"clean\",\"deviceId\":\"3jyun-865353030407958\",\"deviceName\":\"烟感07958\",\"at\":\"2018-11-09
    // 11:18:31\",\"location\":\"北京天安门\"}"]
    // ["{\"deviceType\":\"CTNBSmokeSensor\",\"ext\":{\"IMEI\":\"865352032692781\",\"location\":{\"lon\":113.52228,\"lat\":22.266123}},\"streamId\":\"heartbeat\",\"data\":\"光电探测器设备心跳\",\"level\":0,\"isPopup\":true,\"oid\":1544417585872,\"rawData\":\"020000\",\"type\":\"alarm\",\"deviceId\":\"e7f88930-c445-4c4e-a032-fdc62effc5a0\",\"deviceName\":\"NB-IoT烟感0326\",\"at\":\"2018-12-10
    // 12:53:05\",\"location\":\"珠海市香洲区人民西路880号科利大厦\"}"]

    //消音 ["{\"deviceType\":\"CTNBSmokeSensor\",\"ext\":{\"IMEI\":\"865352032692781\",\"location\":{\"lon\":116.39756,\"lat\":39.906925}},\"streamId\":\"sound\",\"data\":\"[联动]光电探测器消音成功\",\"level\":0,\"isPopup\":true,\"oid\":1545351019958,\"rawData\":\"020700\",\"type\":\"alarm\",\"deviceId\":\"e7f88930-c445-4c4e-a032-fdc62effc5a0\",\"deviceName\":\"NB-IoT烟感\",\"at\":\"2018-12-21 08:10:19\",\"location\":\"北京天安门\"}"]

    @RequestMapping(value = "/handler", method = RequestMethod.POST)
    public Msg handler(@RequestBody String json) {
        JSONObject jobj = JSONObject.parseObject(json);
        String dataType = jobj.getString("type");
        if (dataType.equals("alarm")) {// 报警信息,火警 故障 离线
            AlarmData alarm = JSON.parseObject(json, AlarmData.class);
            Smk_Devices dev = _devSvs.findByImei(alarm.getExt().getIMEI());
            if (dev == null) {
                logger.debug("未找到对应imei的设备");
                return ResultUtil.success();
            }

            Smk_Alarm existAlarm = _alarmSvs.findBySmkDevicesIdAndOid(dev.getId(), alarm.getOid());
            if (existAlarm != null) {// 已存在 则直接返回成功
                return ResultUtil.success();
            }

            if (alarm.getRawData().indexOf("020000") != -1 || alarm.getRawData().indexOf("020D00") != -1) {// 心跳和自检
                Smk_HeartBeat heart = new Smk_HeartBeat();
                try {
                    heart.setAlarmTime(DateUtil.stringToDate(alarm.getAt()));
                    heart.setAlarmDetail(alarm.getData());
                    heart.setOid(alarm.getOid());
                    if (alarm.getRawData().indexOf("020000") != -1)
                        heart.setDataType(1);
                    else
                        heart.setDataType(2);
                    heart.setSmkDevicesId(dev.getId());
                    _heartSvs.save(heart);

                    dev.setDevStatus(1);
                    dev.setUpdateDate(new Date());
                    _devSvs.save(dev);
                } catch (Exception e) {
                    logger.error(e.getMessage());
                }
                return ResultUtil.success();
            }

            Smk_Alarm al = new Smk_Alarm();
            al.setAlarmDetail(alarm.getData());
            al.setOid(alarm.getOid());
            try {
                al.setAlarmTime(DateUtil.stringToDate(alarm.getAt()));
            } catch (ParseException e) {
                logger.error(e.getMessage());
            }
            al.setAlarmStat(1);
            if (alarm.getRawData().indexOf("020100") != -1) {// 020100火警，020200传感器故障，020300低压故障，0099离线告警,020A00,9拆除报警
                al.setAlarmType(2);
            } else if (alarm.getRawData().indexOf("020200") != -1 || alarm.getRawData().indexOf("020300") != -1) {//故障
                al.setAlarmType(3);
            } else if (alarm.getRawData().indexOf("0099") != -1) {//离线
                al.setAlarmType(3);
                dev.setDevStatus(2);
            } else if (alarm.getRawData().indexOf("020A00") != -1) {//拆卸
                al.setAlarmType(4);
            } else if (alarm.getRawData().indexOf("020400") != -1||alarm.getRawData().indexOf("020700") != -1){// 清除报警
                al.setAlarmType(5);
            }
            al.setSmkDevicesId(dev.getId());
            _devSvs.save(dev);
            _alarmSvs.save(al);

            Sys_Log log = new Sys_Log("3jadmin", getLocalIp(), "报警管理",
                    "新增报警：" + dev.getDevId() + "," + al.getAlarmDetail());
            _logSvs.save(log);
            Sys_Department dep = _depSvs.findOneById(dev.getDepartmentId());
            sendingAlarm(dev, dep, alarm);

            List<Integer> ids = new ArrayList<Integer>();
            if (dep != null) {
                for (String str : dep.getTreeRoot().split(",")) {
                    if (str != null && str.length() > 0) {
                        ids.add(Integer.valueOf(str));
                    }
                }
                // 查询有权限的用户名
                List<String> names = _userSvs.findByDepartmentIdIn(dev.getDepartmentId(), ids);
                if (names.size() > 0) {
                    try {
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("deviceName", dev.getDevName());
                        map.put("alarmData", jobj.getString("data"));
                        map.put("msgType", dataType);
                        map.put("rawData", alarm.getRawData());
                        map.put("addr", dev.getInstallAddr());
                        map.put("alarmTime", al.getAlarmTime());

                        MyWebSocket.sendInfo(JSONObject.toJSON(map).toString(), names);
                    } catch (IOException e) {
                        logger.error(e.getMessage());
                    }
                }
            }

        } else if (dataType.equals("clean") && jobj.getString("rawData").indexOf("020400") != -1) {// 消除火警。发送短信和语音
            AlarmData alarm = JSON.parseObject(json, AlarmData.class);
            Smk_Devices dev = _devSvs.findByImei(alarm.getExt().getIMEI());
            if (dev != null) {
                Sys_Department dep = _depSvs.findOneById(dev.getDepartmentId());
                sendingAlarm(dev, dep, alarm);
            }
        } else if (dataType.equals("add")) {// 添加设备
            DeviceMessage msg = JSON.parseObject(json, DeviceMessage.class);
            for (DeviceModal m : msg.getDevices()) {
                Smk_Devices dev = new Smk_Devices();
                dev.setDevId(m.getDeviceId());
                dev.setDevName(m.getDeviceName());
                dev.setDevModel(m.getDeviceTypeName());
                dev.setImei(m.getExtension().getIMEI());
                dev.setDepartmentId(1);
                try {
                    _devSvs.save(dev);
                } catch (DataIntegrityViolationException e) {
                    logger.error(e.getMessage());
                    continue;
                }
                Sys_Log log = new Sys_Log("3jadmin", getLocalIp(), "设备管理", "添加设备：" + dev.getDevId());
                _logSvs.save(log);
            }
        } else if (dataType.equals("update")) {// 修改设备

        } else if (dataType.equals("delete")) {// 删除设备
            DeviceMessage msg = JSON.parseObject(json, DeviceMessage.class);
            String devId = msg.getDevices().get(0).getDeviceId();
            Smk_Devices d = _devSvs.findByDevId(devId);
            if (d != null) {
                _devSvs.deleteById(d.getId());
                logger.debug("设备管理：由推送删除设备:" + devId);
                Sys_Log log = new Sys_Log("3jadmin", getLocalIp(), "设备管理", "删除设备：" + devId);
                _logSvs.save(log);
            }

        }
        return ResultUtil.success();
    }

    @RequestMapping(value = "/push", method = RequestMethod.POST)
    public Msg pushMsg(@RequestBody JSONObject jo) {
        try {
            List<String> names = new ArrayList<String>();
            String str = jo.getString("userid");
            names.add(str);
            MyWebSocket.sendInfo("message", names);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResultUtil.success();
    }

    @RequestMapping(value = "/xy", method = RequestMethod.POST)
    public Msg TestXY(@RequestBody JSONObject jo) {
        try {

            String deviceId = jo.getString("deviceId");
            HttpResult re = _apiSvs.doGetCommand(deviceId, "5859");
            // HttpResult re = _apiSvs.doGetDevDetail(deviceId);
            return ResultUtil.success(re.getBody());
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error(-1, e.getMessage());
        }

    }

    // 批量发送短信
    private void smsBatchSend(String[] mobiles, int template_id, String[] params) {
        SmsSingleSender ssender = new SmsSingleSender(Constants.SHORTMSGAPPID, Constants.SHORTMSGAPPKEY);
        Integer count = 0;
        try {
            for (String mobile : mobiles) {
                SmsSingleSenderResult sendResult = ssender.sendWithParam("86", mobile, template_id, params, "", "", "");
                if (sendResult.result == 0) {
                    Sys_Log log = new Sys_Log("system","0.0.0.0", "发送短信给："+mobile+"模版id:"+template_id, "成功。");
                _logSvs.save(log);
                    count++;
                } else {
                    Sys_Log log = new Sys_Log("system","0.0.0.0", "发送短信给："+mobile+"模版id:"+template_id, "失败："+sendResult.errMsg+","+sendResult.ext);
                    _logSvs.save(log);
                    logger.error("发送短信错误:" + sendResult.errMsg);
                    logger.error("errcode" + sendResult.ext);
                }
            }
            logger.debug("本次需要发送短信数量：" + mobiles.length + "。成功发送：" + count);
        } catch (Exception e) {
            logger.error(e.getMessage());

        }
    }

    private void voiceBatchSend(String[] mobiles, int template_id, String[] params) {
        try {
            TtsVoiceSender vpsender = new TtsVoiceSender(Constants.SHORTMSGAPPID, Constants.SHORTMSGAPPKEY);
            Integer count = 0;
            for (String mobile : mobiles) {
                TtsVoiceSenderResult result = vpsender.send("86", mobile, template_id, params, 2, "");
                if (result.result == 0) {
                    count++;
                    Sys_Log log = new Sys_Log("system","0.0.0.0", "发送语音给："+mobile+"模版id:"+template_id, "成功。");
                _logSvs.save(log);
                } else {
                    
                    Sys_Log log = new Sys_Log("system","0.0.0.0", "发送短信给："+mobile+"模版id:"+template_id, "失败："+result.errMsg+","+result.ext);
                    _logSvs.save(log);
                    logger.error("发送语音错误:" + result.errMsg);
                }
            }
            logger.debug("本次需要发送语音数量：" + mobiles.length + "。成功发送：" + count);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    // 获取报警联系人，并调用批量发送短信
    private void sendingAlarm(Smk_Devices dev, Sys_Department dep, AlarmData alarm) {
        String rawData = alarm.getRawData();
        if (dev.getSmkBuildingId() > 0) {// 设备有挂靠子单位 则发送短信和电话报警,同时发送给网格员，需要查找网格员

            Smk_Buildings building = _buildSvs.findOneById(dev.getSmkBuildingId());
            Smk_GroupCompany gc = _gcSvs.findOneById(building.getSmkGroupCompanyId());
            String[] params = { dep.getDepName(), gc.getGroupName(), building.getName(), dev.getInstallAddr(),
                    "NB烟感设备" };

            List<Sys_User> pushUser = getNeedPushUserByDep(dep);
            List<String> mobilesList = new ArrayList<String>();
            mobilesList.add(building.getManagerMobile());
            // 增加网格员推送
            if (pushUser != null) {
                pushUser.forEach((Sys_User s) -> mobilesList.add(s.getMobile()));
            }
            // 增加紧急联系人推送
            if (building.getAlarmNotifier() != null) {
                String[] contacts = building.getAlarmNotifier().split("\\|");
                if (contacts.length > 0) {
                    for (String contact : contacts) {
                        mobilesList.add(contact.split(",")[1]);
                    }
                }
            }
            String[] mobiles = mobilesList.toArray(new String[mobilesList.size()]);  
            if (rawData.indexOf("020200") != -1 || rawData.indexOf("020300") != -1) {// 故障需要传递故障内容
                // String[] params1 = { dep.getDepName(), gc.getGroupName(), building.getName(), dev.getInstallAddr(),
                //         "烟感设备", alarm.getData() };
                String[] new_params = { building.getName(), dev.getInstallAddr(), dev.getDevName() ,alarm.getData() };
                smsBatchSend(mobiles, Constants.getSmsTemplateid(rawData), new_params);
                voiceBatchSend(mobiles, Constants.getVoiceTemplateid(rawData), new_params);

            } else if (rawData.indexOf("020100") != -1||rawData.indexOf("0099") != -1||rawData.indexOf("020A00") != -1
            ||rawData.indexOf("020700") != -1) {// 火警，离线，拆除，消音   
                String[] new_params = { building.getName(), dev.getInstallAddr(), dev.getDevName() };
                smsBatchSend(mobiles, Constants.getSmsTemplateid(rawData), new_params);
                voiceBatchSend(mobiles, Constants.getVoiceTemplateid(rawData), new_params);
            }
        }
    }

    private List<Sys_User> getNeedPushUserByDep(Sys_Department dep) {
        List<Integer> ids = new ArrayList<Integer>();
        if (dep != null) {
            for (String str : dep.getTreeRoot().split(",")) {
                if (str != null && str.length() > 0) {
                    ids.add(Integer.valueOf(str));
                }
            }
        }
        List<Sys_User> users = _userSvs.findPushByDepartmentIdIn(dep.getId(), ids);
        if (users.size() > 0) {
            return users;
        } else {
            return null;
        }
    }
}